package sjc;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.barriers.DistributedDoubleBarrier;
import org.apache.curator.retry.ExponentialBackoffRetry;

/**
 * 双重屏障，在协作开始之前同步，当足够数量的进程加入到屏障后，开始协作，当所有进程完毕后离开屏障。
 *
 * 1. 每个Barrier的参与者都会在调用DistributedDoubleBarrier.enter()方法之后进行等待，此时处于准备进入状态。
 * 2. 一旦准备进入Barrier的成员数达到指定数量之后，所有的成员会被同时触发进入。
 * 3. 之后调用DistributedDoubleBarrier.leave()方法则会再次等待，此时处于退出状态。
 * 4. 一旦准备退出Barrier的成员数达到5个后，所有的成员同样会被同时触发退出。
 */
public class DistributedDoubleBarrierTest {
    private static final String PATH = "/examples/barrier";

    public static void main(String[] args) throws InterruptedException {
        for(int i=0; i<5; i++){
            final int index = i;

            new Thread(new Runnable() {
                @Override
                public void run() {
                    try{
                        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3, Integer.MAX_VALUE);
                        CuratorFramework client = CuratorFrameworkFactory.newClient("192.168.72.133:2181", 3000, 3000, retryPolicy);
                        client.start();

                        // 当enter()方法被调用时，成员被阻塞，直到所有的成员都调用了enter()。
                        // 当leave()方法被调用时，它也阻塞调用线程， 直到所有的成员都调用了leave()。
                        DistributedDoubleBarrier doubleBarrier = new DistributedDoubleBarrier(client, PATH, 5);

                        System.out.println("线程 " + index + " 等待");
                        doubleBarrier.enter();

                        //调用enter阻塞,直到所有线程都到达之后执行,执行完毕之后，调用leave阻塞,直到所有线程都调用leave

                        System.out.println("线程 " + index + " 已经执行");
                        doubleBarrier.leave();

                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }).start();
        }

        Thread.sleep(Integer.MAX_VALUE);
    }
}
